package com.chaucer.factory;

import com.alibaba.druid.util.StringUtils;
import com.chaucer.annotation.*;
import org.reflections.Reflections;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author 应癫
 *
 * 工厂类，生产对象（使用反射技术）
 */
public class BeanFactory {

    /**
     * 任务一：读取解析xml，通过反射技术实例化对象并且存储待用（map集合）
     * 任务二：对外提供获取实例对象的接口（根据id获取）
     */
    @Autowired
    private ProxyFactory proxyFactory;

    private static Map<String, Object> map = new HashMap<>();  // 存储对象

    static {
        //第一步：扫描包，分析出需要实例化的对象并存储
        //获取反射对象集合
        Reflections reflections = new Reflections("com.chaucer");
        Set<Class<?>> serviceAnnotation = reflections.getTypesAnnotatedWith(Service.class);
        serviceAnnotation.forEach(aClass -> {
            if (aClass.isAnnotationPresent(Service.class)) {
                Service service = aClass.getAnnotation(Service.class);
                createBean(aClass,service.value());
            }
        });
//        Set<Class<?>> componentAnnotation = reflections.getTypesAnnotatedWith(Component.class);
//        componentAnnotation.forEach(aClass -> {
//            if (aClass.isAnnotationPresent(Component.class)) {
//                Component component = aClass.getAnnotation(Component.class);
//                if(!aClass.isAnnotation()) {
//                    createBean(aClass, component.value());
//                }
//            }
//        });
        map.forEach((key, value) -> {
            Class<?> aClass = value.getClass();
            Field[] declaredFields = aClass.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                if (!declaredField.isAnnotationPresent(Autowired.class)) {
                    continue;
                }
                declaredField.setAccessible(true);
                try {
                    declaredField.set(value, getBean(declaredField.getName()));
                } catch (IllegalAccessException e) {
//                    e.printStackTrace();
                }
            }

//            if (aClass.getDeclaredMethods()..isAnnotationPresent(Transactional.class)) {
//                //被代理对象
//                Object object = value;
//                //进行代理转为代理对象
//                ProxyFactory proxyFactory = (ProxyFactory) map.get("proxyFactory");
//                //判断对象是否实现接口 是则使用jdk 否则cgLib
//                Class<?>[] interfaces = aClass.getInterfaces();
//                if (interfaces.length > 0) {
//                    object = proxyFactory.getJdkProxy(object);
//                }else {
//                    object = proxyFactory.getCglibProxy(object);
//                }
//                //使用代理对象覆盖原对象
//                map.put(key, object);
//            }
        });
        map.forEach((key, value) -> {
            Class<?> aClass = value.getClass();
            Method[] declaredMethods = aClass.getDeclaredMethods();
            for (Method method : declaredMethods) {
                Annotation[] declaredAnnotations = method.getDeclaredAnnotations();
                for (Annotation declaredAnnotation : declaredAnnotations) {
                    if (Transactional.class.getName().equals(declaredAnnotation.annotationType().getName())) {
                        //被代理对象
                        Object object = value;
                        //进行代理转为代理对象
                        ProxyFactory proxyFactory = (ProxyFactory) map.get("proxyFactory");
                        //判断对象是否实现接口 是则使用jdk 否则cgLib
                        Class<?>[] interfaces = aClass.getInterfaces();
                        if (interfaces.length > 0) {
                            object = proxyFactory.getJdkProxy(object);
                        } else {
                            object = proxyFactory.getCglibProxy(object);
                        }
                        //使用代理对象覆盖原对象
                        map.put(key, object);
                    }
                }
            }
        });
    }
    private static void createBean(Class<?> aClass, String value) {

        Object o = null;  // 实例化之后的对象
        try {
            o = aClass.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        if (aClass.isAnnotationPresent(Service.class)) {
            Service annotation = aClass.getAnnotation(Service.class);
            //如果service注解value值存在且不空时  使用 value 否则使用类名（首字母小写）
            if (StringUtils.isEmpty(annotation.value())) {
                String className = aClass.getSimpleName();
                map.put(decapitalize(className), o);
            } else {
                map.put(annotation.value(), o);
            }// 存储到map中待用
        }
//        } else if (aClass.isAnnotationPresent(Component.class)) {
//            String className = aClass.getSimpleName();
//            map.put(decapitalize(className), o);
//        }

    }
    // 任务二：对外提供获取实例对象的接口（根据id获取）
    public static Object getBean(String id) {
        return map.get(id);
    }

    public static String decapitalize(String name) {
        if (name == null || name.length() == 0) {
            return name;
        }
        if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
                Character.isUpperCase(name.charAt(0))){
            return name;
        }
        char[] chars = name.toCharArray();
        chars[0] = Character.toLowerCase(chars[0]);
        return new String(chars);
    }

}

